home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / libs / wbstartlib.lha / WBStart / src / start.c < prev    next >
C/C++ Source or Header  |  1996-03-13  |  12KB  |  472 lines

  1. /*
  2.  * start.c  V2.0
  3.  *
  4.  * Start a Workbench program
  5.  *
  6.  * (c) 1991-1996 Stefan Becker
  7.  */
  8.  
  9. #include "wbstart.h"
  10.  
  11. /* Local data structure */
  12. struct ProcessData {
  13.  struct WBStartup  pd_WBStartup;
  14.  BPTR              pd_HomeDir;
  15.  ULONG             pd_StackSize;
  16.  struct WBArg     *pd_CurrentArg;
  17.  /* Array of WBArgs follows */
  18. };
  19.  
  20. /* Local data */
  21. static const struct TagItem ProcTags[] = {
  22.  NP_FreeSeglist, FALSE,
  23.  NP_Input,       NULL,
  24.  NP_CloseInput,  FALSE,
  25.  NP_Output,      NULL,
  26.  NP_CloseOutput, FALSE,
  27.  NP_Error,       NULL,
  28.  NP_CloseError,  FALSE,
  29.  NP_CurrentDir,  NULL,  /* Makes sure that you don't see the guy from India */
  30.  NP_ConsoleTask, NULL,
  31.  NP_WindowPtr,   NULL,
  32.  TAG_DONE
  33. };
  34.  
  35. /* Duplicate a string */
  36. static char *StrDup(char *orig)
  37. {
  38.  char *rc;
  39.  
  40.  /* Allocate memory for string and copy it */
  41.  if (rc = AllocateMemory(strlen(orig) + 1)) strcpy(rc, orig);
  42.  
  43.  return(rc);
  44. }
  45.  
  46. /* Copy argument list */
  47. static BOOL CopyArguments(struct ProcessData *pd, struct WBArg *orig,
  48.                           ULONG count)
  49. {
  50.  struct WBArg *dest = pd->pd_CurrentArg;
  51.  BOOL rc            = TRUE;
  52.  
  53.  /* Scan original list */
  54.  while (count--) {
  55.  
  56.   DEBUGLOG(kprintf("Copy in : Lock: 0x%08lx, Name: %s (0x%08lx)\n",
  57.                    orig->wa_Lock, orig->wa_Name, orig->wa_Name);)
  58.  
  59.   /* Duplicate name and lock (NULL locks are only allowed for devices!) */
  60.   if (((dest->wa_Name = StrDup(orig->wa_Name)) == NULL) ||
  61.       (pd->pd_WBStartup.sm_NumArgs++,
  62.        (((dest->wa_Lock = DupLock(orig->wa_Lock)) == NULL) &&
  63.         (dest->wa_Name[strlen(dest->wa_Name) - 1] != ':')))) {
  64.  
  65.    /* Error */
  66.    rc = FALSE;
  67.  
  68.    /* Leave loop */
  69.    break;
  70.   }
  71.  
  72.   DEBUGLOG(kprintf("Copy Out: Lock: 0x%08lx, Name: %s (0x%08lx)\n",
  73.                    dest->wa_Lock, dest->wa_Name, dest->wa_Name);)
  74.  
  75.   /* Next entries */
  76.   orig++;
  77.   dest++;
  78.  }
  79.  
  80.  return(rc);
  81. }
  82.  
  83. /* Fill current WBArg */
  84. static BOOL FillCurrentArg(struct ProcessData *pd, BPTR currentdir, char *name)
  85. {
  86.  struct WBArg *wa = pd->pd_CurrentArg++;
  87.  BOOL rc          = FALSE;
  88.  
  89.  DEBUGLOG(kprintf("Fill in : Lock: 0x%08lx, Name: %s\n", currentdir, name);)
  90.  
  91.  /* Duplicate name */
  92.  if (wa->wa_Name = StrDup(name)) {
  93.   char *endpath;
  94.  
  95.   /* Increment argument count */
  96.   pd->pd_WBStartup.sm_NumArgs++;
  97.  
  98.   /* Clear lock */
  99.   wa->wa_Lock = NULL;
  100.  
  101.   /* Does name contain a path? */
  102.   if ((endpath = PathPart(wa->wa_Name)) != wa->wa_Name) {
  103.  
  104.    /* Yes, set string terminator */
  105.    *endpath = '\0';
  106.  
  107.    /* Get lock to new directory */
  108.    if (wa->wa_Lock = Lock(wa->wa_Name, ACCESS_READ)) {
  109.  
  110.     /* Copy file part again */
  111.     strcpy(wa->wa_Name, FilePart(name));
  112.  
  113.     /* All OK */
  114.     rc = TRUE;
  115.    }
  116.  
  117.   } else
  118.  
  119.    /* No, just duplicate current dir lock */
  120.    rc = (wa->wa_Lock = DupLock(currentdir)) != NULL;
  121.  }
  122.  
  123.  DEBUGLOG(kprintf("Fill out: Lock: 0x%08lx, Name: %s\n", wa->wa_Lock,
  124.                                                          wa->wa_Name);)
  125.  
  126.  return(rc);
  127. }
  128.  
  129. /* Load program code */
  130. static BOOL LoadProgram(struct ProcessData *pd, BPTR currentdir, char *name)
  131. {
  132.  BPTR oldlock;
  133.  struct DiskObject *dobj;
  134.  BOOL rc                 = FALSE;
  135.  
  136.  DEBUGLOG(kprintf("Current Dir: 0x%08lx\n", currentdir);)
  137.  
  138.  /* Go to current directory */
  139.  oldlock = CurrentDir(currentdir);
  140.  
  141.  DEBUGLOG(kprintf("Load Icon: %s\n", name);)
  142.  
  143.  /* Get icon and check for projects */
  144.  if (dobj = GetDiskObject(name)) {
  145.  
  146.   /* Get stack size */
  147.   pd->pd_StackSize = dobj->do_StackSize;
  148.  
  149.   /* Check icon type */
  150.   switch (dobj->do_Type) {
  151.  
  152.    case WBTOOL:      /* Program is a TOOL */
  153.  
  154.     DEBUGLOG(kprintf("Tool icon\n");)
  155.  
  156.     /* Fill first WBArg */
  157.     rc = FillCurrentArg(pd, currentdir, name);
  158.  
  159.     /* Get home directory */
  160.     pd->pd_HomeDir = pd->pd_WBStartup.sm_ArgList->wa_Lock;
  161.     break;
  162.  
  163.    case WBPROJECT: { /* Program is a PROJECT */
  164.      char *tool = dobj->do_DefaultTool;
  165.  
  166.      DEBUGLOG(kprintf("Project icon, Tool: %s\n", tool);)
  167.  
  168.      /* Does the default tool contain a relative/absolute path? */
  169.      if (FilePart(tool) != tool) {
  170.  
  171.       /* Yes, fill first WBArg with default tool, second with project */
  172.       if (rc = (FillCurrentArg(pd, currentdir, tool) &&
  173.                 FillCurrentArg(pd, currentdir, name)))
  174.  
  175.        /* Get home directory */
  176.        pd->pd_HomeDir = pd->pd_WBStartup.sm_ArgList->wa_Lock;
  177.  
  178.      } else {
  179.       struct WBArg *first = pd->pd_WBStartup.sm_ArgList;
  180.  
  181.       /* No, fill first WBArg with project, second with default tool, */
  182.       /* but use the projects directory lock as current dir lock      */
  183.       if (rc = (FillCurrentArg(pd, currentdir, name) &&
  184.                 FillCurrentArg(pd, first->wa_Lock, tool))) {
  185.         struct WBArg temp;
  186.         struct WBArg *second = first + 1;
  187.  
  188.         /* Now swap first and second WBArg */
  189.         temp    = *first;
  190.         *first  = *second;
  191.         *second = temp;
  192.  
  193.         /* Scan load path for default tool */
  194.         pd->pd_HomeDir = ScanLoadPath(tool, currentdir);
  195.       }
  196.      }
  197.     }
  198.     break;
  199.   }
  200.  
  201.   /* Free icon */
  202.   FreeDiskObject(dobj);
  203.  
  204.   /* No icon. This is a special case which can never happen with    */
  205.   /* the Workbench. In this case the Workbench starts a CLI process */
  206.  } else {
  207.  
  208.   DEBUGLOG(kprintf("No program icon found\n");)
  209.  
  210.   /* Which one of the two alternatives is correct? IMHO the second one */
  211. #if 0
  212.   /* Program is a TOOL. Fill first WBArg */
  213.   rc = FillCurrentArg(pd, currentdir, name);
  214.  
  215.   /* Get home directory */
  216.   pd->pd_HomeDir = pd->pd_WBStartup.sm_ArgList->wa_Lock;
  217. #else
  218.   /* Get home directory */
  219.   pd->pd_HomeDir = ScanLoadPath(name, currentdir);
  220.  
  221.   /* Again two alternatives: First argument in current or home directory? */
  222.   /* Some programs seem only to work with the second alternative...       */
  223. #if 1
  224.   /* Program is a TOOL. Fill first WBArg */
  225.   rc = FillCurrentArg(pd, currentdir, name);
  226. #else
  227.   /* Program is a TOOL. Fill first WBArg */
  228.   rc = FillCurrentArg(pd, pd->pd_HomeDir, name);
  229. #endif
  230. #endif
  231.  }
  232.  
  233.  /* All OK? */
  234.  if (rc) {
  235.   char *tool = pd->pd_WBStartup.sm_ArgList->wa_Name;
  236.  
  237.   /* Yes, go to home directory */
  238.   CurrentDir(pd->pd_HomeDir);
  239.  
  240.   DEBUGLOG(kprintf("Loading program\n");)
  241.  
  242.   /* Load program */
  243.   if (rc = ((pd->pd_WBStartup.sm_Segment = NewLoadSeg(tool, NULL)) != NULL)) {
  244.  
  245.    DEBUGLOG(kprintf("Program loaded, retrieving icon\n");)
  246.  
  247.    /* Get tool icon */
  248.    if (dobj = GetDiskObject(tool)) {
  249.  
  250.     /* Copy Toolwindow */
  251.     if (dobj->do_ToolWindow)
  252.      rc = ((pd->pd_WBStartup.sm_ToolWindow = StrDup(dobj->do_ToolWindow))
  253.             != NULL);
  254.  
  255.     /* Free icon */
  256.     FreeDiskObject(dobj);
  257.    }
  258.   }
  259.  
  260.   DEBUGLOG(kprintf("Tool: %s, Home: 0x%08lx, Stack %ld\n",
  261.                    tool, pd->pd_HomeDir, pd->pd_StackSize);)
  262.  }
  263.  
  264.  /* Go back to old directory */
  265.  CurrentDir(oldlock);
  266.  
  267.  return(rc);
  268. }
  269.  
  270. /* Start a Workbench program */
  271. LONG StartProgram(struct TagItem *tags)
  272. {
  273.  LONG rc            = RETURN_FAIL;
  274.  char *name         = NULL;
  275.  BPTR dirlock       = NULL;
  276.  LONG priority      = 0;
  277.  ULONG stack        = 0;
  278.  ULONG count        = 0;
  279.  struct WBArg *args = NULL;
  280.  
  281.  /* Scan tag items */
  282.  {
  283.   struct TagItem *tstate = tags;
  284.   struct TagItem *ti;
  285.  
  286.   /* Get next tag item */
  287.   while (ti = NextTagItem(&tstate)) {
  288.  
  289.    DEBUGLOG(kprintf("Tag: 0x%08lx, Data: 0x%08lx\n", ti->ti_Tag, ti->ti_Data);)
  290.  
  291.    /* Which tag? */
  292.    switch (ti->ti_Tag) {
  293.  
  294.     case WBStart_Name:
  295.      name = (char *) ti->ti_Data;
  296.      break;
  297.  
  298.     case WBStart_DirectoryName:
  299.      if (ti->ti_Data) {
  300.       BPTR newlock;
  301.  
  302.       /* Get new lock */
  303.       if (newlock = Lock((STRPTR) ti->ti_Data, ACCESS_READ)) {
  304.  
  305.        DEBUGLOG(kprintf("Locked %s (0x%08lx), Unlocking 0x%08lx\n",
  306.                         ti->ti_Data, newlock, dirlock);)
  307.  
  308.        /* Release old directory lock first */
  309.        UnLock(dirlock);
  310.  
  311.        /* Set new lock */
  312.        dirlock = newlock;
  313.       }
  314.      }
  315.      break;
  316.  
  317.     case WBStart_DirectoryLock: {
  318.       BPTR newlock;
  319.  
  320.       /* Duplicate lock */
  321.       if (newlock = DupLock(ti->ti_Data)) {
  322.  
  323.        DEBUGLOG(kprintf("Duplicated 0x%08lx (0x%08lx), Unlocking 0x%08lx\n",
  324.                         ti->ti_Data, newlock, dirlock);)
  325.  
  326.        /* Release old directory lock first */
  327.        UnLock(dirlock);
  328.  
  329.        /* Set new lock */
  330.        dirlock = newlock;
  331.       }
  332.      }
  333.      break;
  334.  
  335.     case WBStart_Stack:
  336.      stack = ti->ti_Data;
  337.      break;
  338.  
  339.     case WBStart_Priority:
  340.      priority = ti->ti_Data;
  341.      break;
  342.  
  343.     case WBStart_ArgumentCount:
  344.      count = ti->ti_Data;
  345.      break;
  346.  
  347.     case WBStart_ArgumentList:
  348.      args = (struct WBArg *) ti->ti_Data;
  349.      break;
  350.    }
  351.   }
  352.  
  353.   DEBUGLOG(kprintf("Tags parsed.\n");)
  354.  }
  355.  
  356.  /* Parameter check                                                      */
  357.  /* a) Name must be specified                                            */
  358.  /* b) If argument list is specified then argument must be specified too */
  359.  if (name && ((args == NULL) || (count != 0))) {
  360.   struct ProcessData *pd;
  361.  
  362.   DEBUGLOG(kprintf(
  363.            "Name: %s, Stack: %ld, Prio: %ld, Count: %ld, Args: 0x%08lx\n",
  364.            name, stack, priority, count, args);)
  365.  
  366.   /* Sanity check for argument count */
  367.   if (args == NULL) count = 0;
  368.  
  369.   /* Sanity check for stack size */
  370.   if (stack < 4096) stack = 4096;
  371.  
  372.   /* Allocate WBStartup structure and argument array     */
  373.   /* Note that we reserve memory for two more arguments! */
  374.   if (pd = AllocateMemory(sizeof(struct ProcessData) +
  375.                           sizeof(struct WBArg) * (count + 2))) {
  376.  
  377.    /* Initialize ProcessData structure */
  378.    pd->pd_WBStartup.sm_Message.mn_Node.ln_Pri = 0;
  379.    pd->pd_WBStartup.sm_Message.mn_ReplyPort   = WBStartBase->wbsb_Port;
  380.    pd->pd_WBStartup.sm_Message.mn_Length      = sizeof(struct WBStartup);
  381.    pd->pd_WBStartup.sm_Segment                = NULL;
  382.    pd->pd_WBStartup.sm_NumArgs                = 0;
  383.    pd->pd_WBStartup.sm_ToolWindow             = NULL;
  384.    pd->pd_WBStartup.sm_ArgList                = (struct WBArg *) (pd + 1);
  385.    pd->pd_StackSize                           = stack;
  386.    pd->pd_CurrentArg                          = pd->pd_WBStartup.sm_ArgList;
  387.  
  388.    /* Load program code */
  389.    if (LoadProgram(pd, dirlock, name)) {
  390.  
  391.     /* Copy argument list */
  392.     if (CopyArguments(pd, args, count)) {
  393.      BPTR homelock;
  394.  
  395.      /* Duplicate home directory lock */
  396.      if (homelock = DupLock(pd->pd_HomeDir)) {
  397.       struct Process *newproc;
  398.  
  399.       /* Create new process */
  400.       if (newproc = CreateNewProcTags(
  401.            NP_Seglist,   pd->pd_WBStartup.sm_Segment,
  402.            NP_StackSize, (stack > pd->pd_StackSize) ? stack : pd->pd_StackSize,
  403.            NP_Name,      pd->pd_WBStartup.sm_ArgList->wa_Name,
  404.            NP_Priority,  priority,
  405.            NP_HomeDir,   homelock,
  406.  
  407.            /* The rest is constant */
  408.            TAG_MORE,      ProcTags)) {
  409.        struct MsgPort *p = &newproc->pr_MsgPort;
  410.  
  411.        DEBUGLOG(kprintf("New process created: 0x%08lx\n", newproc);)
  412.  
  413.        /* Set WBStartup process pointer */
  414.        pd->pd_WBStartup.sm_Process = p;
  415.  
  416.        /* Send startup message to new process */
  417.        PutMsg(p, (struct Message *) pd);
  418.  
  419.        /* All OK */
  420.        rc = RETURN_OK;
  421.  
  422.       } else
  423.         /* Process not created,  free duplicate of home directory lock */
  424.         UnLock(homelock);
  425.      }
  426.     }
  427.    }
  428.  
  429.    /* Error? */
  430.    if (rc != RETURN_OK) FreeProcessData((struct Message *) pd, FALSE);
  431.   }
  432.  }
  433.  
  434.  /* Free directory lock */
  435.  UnLock(dirlock);
  436.  
  437.  return(rc);
  438. }
  439.  
  440. /* Free process data */
  441. void FreeProcessData(struct Message *msg, BOOL reply)
  442. {
  443.  struct ProcessData *pd = (struct ProcessData *) msg;
  444.  struct WBArg *wa       = pd->pd_WBStartup.sm_ArgList;
  445.  int i                  = pd->pd_WBStartup.sm_NumArgs;
  446.  
  447.  /* Scan array */
  448.  while (i--) {
  449.  
  450.   DEBUGLOG(kprintf("Free WBArg %s (0x%08lx)\n", wa->wa_Name, wa->wa_Lock);)
  451.  
  452.   /* Free directory lock */
  453.   UnLock(wa->wa_Lock);
  454.  
  455.   /* Free name buffer */
  456.   if (wa->wa_Name) FreeMemory(wa->wa_Name);
  457.  
  458.   /* Next entry */
  459.   wa++;
  460.  }
  461.  
  462.  /* Free tool window specificaton */
  463.  if (pd->pd_WBStartup.sm_ToolWindow)
  464.   FreeMemory(pd->pd_WBStartup.sm_ToolWindow);
  465.  
  466.  /* Free program segments */
  467.  if (pd->pd_WBStartup.sm_Segment) UnLoadSeg(pd->pd_WBStartup.sm_Segment);
  468.  
  469.  /* Free process data structure */
  470.  FreeMemory(pd);
  471. }
  472.